﻿using Silverstone;

namespace Silversocial.Client.Modules
{
    /// <summary>
    ///     ViewModel for the login page
    /// </summary>
    public class LoginViewModel : ViewModelBase<ILoginView, LoginViewModel>
    {
        // Dependencies
        private readonly IAppShell shell;
        private readonly ILoginDataProvider dataProvider;

        // Commands
        private readonly ICommand login;
        private readonly ICommand register;

        // Data Fields
        private readonly User user = new User();
        private bool isLoggingIn;

        public LoginViewModel(IAppShell shell, ILoginDataProvider dataProvider)
        {
            this.shell = shell;
            this.dataProvider = dataProvider;
            this.login = new LoginCommand(this);
            this.register = new RegisterCommand(this);
        }

        /// <summary>
        ///     Gets the user being logged in
        /// </summary>
        public User User
        {
            get { return this.user; }
        }

        /// <summary>
        ///     Gets or sets whether the user is currently being logged in
        /// </summary>
        public bool IsLoggingIn
        {
            get { return isLoggingIn; }
            set
            {
                isLoggingIn = value;
                this.RaisePropertyChanged(v => v.IsLoggingIn);
            }
        }

        /// <summary>
        ///     Gets the command used to login the user
        /// </summary>
        public ICommand Login
        {
            get { return this.login; }
        }

        /// <summary>
        ///     Gets the command used to register a new user
        /// </summary>
        public ICommand Register
        {
            get { return register; }
        }

        private class LoginCommand : CommandBase
        {
            public LoginCommand(LoginViewModel viewModel) : base(viewModel)
            {
                this.ViewModel.dataProvider.ValidateUserCompleted += this.HandleValidateUserCompleted;
                this.ViewModel.User.PropertyChanged += delegate { 
                    this.RaiseCanExecuteChanged(); };
            }

            public override bool CanExecute(object parameter)
            {
                // Used to inform the command framework that we can only login once the user 
                // has entered a username and password and we are not already in the middle of a login
                return !string.IsNullOrEmpty(this.ViewModel.User.Username) 
                    && !string.IsNullOrEmpty(this.ViewModel.User.Password) 
                    && !this.ViewModel.IsLoggingIn;
            }

            public override void Execute(object parameter)
            {
                // Record that we are currently in the middle of a login attempt
                this.ViewModel.IsLoggingIn = true;

                // Call the Async method on the data provider to validate the user.  The ViewModel will 
                // handle the response to this method
                this.ViewModel.dataProvider.ValidateUser(this.ViewModel.User);
            }

            private void HandleValidateUserCompleted(object sender, ValidateUserCompletedEventArgs e)
            {
                // Record that we have finished attempting to log in
                this.ViewModel.IsLoggingIn = false;

                if (e.Successful)
                {
                    this.ViewModel.shell.User = this.ViewModel.User;
                    this.ViewModel.shell.Navigate<IFriendListView>();
                }
                else
                {
                    this.ViewModel.View.LoginUnsuccessful();
                }

                // Raise the "CanExecuteChanged" event
                this.RaiseCanExecuteChanged();
            }

        }

        private class RegisterCommand : CommandBase
        {
            public RegisterCommand(LoginViewModel viewModel) : base(viewModel)
            {
            }

            public override void Execute(object parameter)
            {
                // Simply use the shell to navigate to the register view when this command is executed
                this.ViewModel.shell.Navigate<IRegisterView>();
            }
        }
    }
}
